﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Microsoft.Win32.SafeHandles;
using Dali.Command;
using Dali.Response;
using System.Diagnostics;
using System.Threading;

namespace DaliUsb
{
  public static class TridonicDaliUsb
  {
    private static readonly object ioLock = new object();
    private static FileStream fs;

    public static IEnumerable<string> FindDevicePaths()
    {
      Guid hidGuid;

      hidGuid = HID.GetHidGuid();
      return SetupApi.FindDevicePath(hidGuid, 0x17b5, 0x20);
    }

    public static DaliResponse SendCommand(DaliCommand command, string devicePath)
    {
      SafeFileHandle handle;
      DaliResponse res;
      byte[] cmd;

      lock (ioLock)
      {
        handle = Kernel32.CreateFile(devicePath, FileAccess.ReadWrite, FileShare.None, IntPtr.Zero, FileMode.Open, EFileAttributes.Overlapped, IntPtr.Zero);
        fs = new FileStream(handle, FileAccess.ReadWrite, 65, true);
        fs.ReadTimeout = 100;

        try
        {
          Trace.TraceInformation("Writing USB command");
          cmd = command.GetHidCommand();
          fs.Write(cmd, 0, cmd.Length);
          Trace.TraceInformation("Done writing USB command");

          Trace.TraceInformation("Reading USB command");

          if (command is QueryActualLevel)
          {
            res = new ActualLevel();
          }
          else if (command is QueryMinLevel)
          {
            res = new MinLevel();
          }
          else if (command is QueryMaxLevel)
          {
            res = new MaxLevel();
          }
          else if (command is QueryGroups_0_7)
          {
            res = new Groups_0_7();
          }
          else if (command is QueryGroups_8_15)
          {
            res = new Groups_8_15();
          }
          else
          {
            res = new DaliResponse();
          }
          
          fs.Read(res.HidCommand, 0, res.HidCommand.Length);
          Trace.TraceInformation("Done reading USB command");

          return res;
        }
        finally
        {
          fs.Close();
          fs.Dispose();
          handle.Close();
          handle.Dispose();
        }
      }
    }
  }
}
